/*
 * 描述： <描述>
 * 修改人： rain
 * 修改时间： 2016年1月22日
 * 项目： rainhy-cores-core
 */
package com.rainhy.core.util;

import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;

import com.rainhy.RainhyConstant;
import com.rainhy.core.support.sort.RandomComparator;

/**
 * Rainhy 随机工具
 * 
 * @author rain
 * @version [版本号, 2016年1月22日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public abstract class RandomUtils {
    
    /** 随机比较器 */
    private static final RandomComparator<Object> randomComparator = new RandomComparator<>();
    
    /** 随机器 */
    private static final Random RANDOM = new Random();
    
    /** 返回随机的 boolean 值 */
    public static boolean nextBoolean() {
        return RANDOM.nextBoolean();
    }
    
    /**
     * <p>
     * Creates an array of random bytes.
     * </p>
     * 
     * @param count the size of the returned array
     * @return the random byte array
     * @throws IllegalArgumentException if {@code count} is negative
     */
    public static byte[] nextBytes(final int count) {
        return org.apache.commons.lang3.RandomUtils.nextBytes(count);
    }
    
    /**
     * 
     * 返回随机字符
     *
     * @return
     * 
     * @return String [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static String nextChineseCharacter() {
        String str = null;
        
        int hightPos = 176 + nextInt(0, 39);
        int lowPos = 161 + nextInt(0, 39);
        
        byte[] b = new byte[2];
        
        b[0] = Integer.valueOf(hightPos).byteValue();
        b[1] = Integer.valueOf(lowPos).byteValue();
        try {
            str = new String(b, "GBK");
        } catch (UnsupportedEncodingException e) {
            str = new String(b);
            System.err.println("不支持gbk编码");
        }
        
        return str;
    }
    
    /**
     * 
     * 返回随机的中文字符
     *
     * @param count 字符个数
     * 
     * @return String 返回的中文字符串
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static String nextChineseCharacter(int count) {
        AssertUtils.isTrue(count > 0, "只能传入大于0的整数 : {}", count);
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(nextChineseCharacter());
        }
        return sb.toString();
    }
    
    /**
     * <p>
     * Returns a random double within the specified range.
     * </p>
     * 
     * @param startInclusive the smallest value that can be returned, must be non-negative
     * @param endInclusive the upper bound (included)
     * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative
     * @return the random double
     */
    public static double nextDouble(final double startInclusive, final double endInclusive) {
        return org.apache.commons.lang3.RandomUtils.nextDouble(startInclusive, endInclusive);
    }
    
    /**
     * <p>
     * Returns a random float within the specified range.
     * </p>
     * 
     * @param startInclusive the smallest value that can be returned, must be non-negative
     * @param endInclusive the upper bound (included)
     * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative
     * @return the random float
     */
    public static float nextFloat(final float startInclusive, final float endInclusive) {
        return org.apache.commons.lang3.RandomUtils.nextFloat(startInclusive, endInclusive);
    }
    
    /**
     * <p>
     * Returns a random integer within the specified range.
     * </p>
     * 
     * @param startInclusive the smallest value that can be returned, must be non-negative
     * @param endExclusive the upper bound (not included)
     * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative
     * @return the random integer
     */
    public static int nextInt(final int startInclusive, final int endExclusive) {
        return org.apache.commons.lang3.RandomUtils.nextInt(startInclusive, endExclusive);
    }
    
    /**
     * <p>
     * Returns a random long within the specified range.
     * </p>
     * 
     * @param startInclusive the smallest value that can be returned, must be non-negative
     * @param endExclusive the upper bound (not included)
     * @throws IllegalArgumentException if {@code startInclusive > endExclusive} or if {@code startInclusive} is negative
     * @return the random long
     */
    public static long nextLong(final long startInclusive, final long endExclusive) {
        return org.apache.commons.lang3.RandomUtils.nextLong(startInclusive, endExclusive);
    }
    
    /**
     * 
     * 随机返回模板字符组中的字符
     *
     * @param template 模板字符组
     * 
     * @return String [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月9日]
     * @author rain
     */
    public static char nextString(char[] template) {
        AssertUtils.isFalse(ArrayUtils.isEmpty(template), "模板字符组不为空");
        return template[nextInt(0, template.length)];
    }
    
    /**
     * 
     * 从指定字符中返回随机长度的字符串
     *
     * @param template 字符模板组
     * @param count 字符串长度
     * 
     * @return String [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月9日]
     * @author rain
     */
    public static String nextString(char[] template, int count) {
        AssertUtils.isTrue(count > 0, "只能传入大于0的整数 : {}", count);
        AssertUtils.isFalse(ArrayUtils.isEmpty(template), "模板字符组不为空");
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(template[nextInt(0, template.length)]);
        }
        return sb.toString();
    }
    
    /**
     * 
     * 返回随机长度的字符串
     *
     * @param count 字符串长度
     * 
     * @return String [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年8月9日]
     * @author rain
     */
    public static String nextString(int count) {
        return nextString(RainhyConstant.COMMON_STRING_CHAR_FULL, count);
    }
    
    /**
     * 
     * 从集合中随机抽取一个对象
     *
     * @param cols 集合
     * 
     * @return T 抽取到的对象
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    @SuppressWarnings("unchecked")
    public static <T> T random(Collection<T> cols) {
        if (CollectionUtils.isEmpty(cols)) {
            return null;
        }
        return (T) random(cols.toArray());
    }
    
    /**
     * 
     * 从数组中随机抽取一个对象
     * 
     * @param ts 数组
     * 
     * @return T 抽出的对象
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static <T> T random(T[] ts) {
        if (ArrayUtils.isEmpty(ts)) {
            return null;
        }
        return ts[nextInt(0, ts.length)];
    }
    
    /**
     * 
     * 随机排序
     *
     * @param cols 集合
     * 
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     * @version [版本号, 2016年1月21日]
     * @author rain
     */
    public static <T> void randomSort(List<T> cols) {
        Collections.sort(cols, randomComparator);
    }
}
